package com.ts.api.module.api.wake.impl;

import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.date.DateUtils;
import com.gitee.apanlh.util.reflection.CopyUtils;
import com.gitee.apanlh.util.valid.RegexUtils;
import com.gitee.apanlh.util.valid.ValidParam;
import com.ts.api.common.constant.common.CommonConstant;
import com.ts.api.common.constant.productflow.ProductApplyFlowStatusEnum;
import com.ts.api.common.redis.DataExchangeRedisKey;
import com.ts.api.common.util.ExceptionUtils;
import com.ts.api.exp.ApiMsgException;
import com.ts.api.module.api.entity.ApiUserRequest;
import com.ts.api.module.api.entity.bo.ApiBizMatchBO;
import com.ts.api.module.api.entity.bo.ApiWakeBO;
import com.ts.api.module.api.entity.bo.ApiWakeUserBO;
import com.ts.api.module.api.entity.po.ApiKeyPO;
import com.ts.api.module.api.wake.WakeService;
import com.ts.api.module.channel.entity.po.ChannelUserFormFieldPO;
import com.ts.api.module.channel.entity.po.ChannelUserFormPO;
import com.ts.api.module.channel.entity.po.ChannelUserRegisterPO;
import com.ts.api.module.channel.entity.qo.ChannelUserQO;
import com.ts.api.module.channel.service.ChannelFormService;
import com.ts.api.module.channel.service.ChannelHistoryFormService;
import com.ts.api.module.channel.service.ChannelHistoryUserService;
import com.ts.api.module.channel.service.ChannelUserService;
import com.ts.api.module.match.plan.PlanDataExchangeFacade;
import com.ts.api.module.match.plan.apply.PlanApplyService;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributeResult;
import com.ts.api.module.match.plan.internal.qualification.model.PlanQualificationError;
import com.ts.api.module.match.plan.internal.qualification.model.PlanQualificationResult;
import com.ts.api.module.match.plan.model.ApiWakePlanMatch;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import com.ts.api.module.product.service.ProductApplyFlowService;
import com.ts.cache.apikey.ApiKeyCacheService;
import com.ts.cache.apikey.entity.ApiKeyCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class WakeServiceImpl implements WakeService {

    private static final List<String> NUMBER_SUFFIX = createFilterUserName();

    @Lazy
    @Autowired
    private ChannelUserService channelUserService;
    @Lazy
    @Autowired
    private ChannelFormService channelFormService;
    @Lazy
    @Autowired
    private ApiKeyCacheService apiKeyCacheService;
    @Lazy
    @Autowired
    private ChannelHistoryUserService channelHistoryUserService;
    @Lazy
    @Autowired
    private ChannelHistoryFormService channelHistoryFormService;
    @Lazy
    @Autowired
    private PlanDataExchangeFacade planDataExchangeFacade;
    @Lazy
    @Autowired
    private PlanApplyService planApplyService;
    @Autowired
    @Lazy
    private ProductApplyFlowService productApplyFlowService;

    @Override
    public void wake(ApiWakeBO apiWakeBO, ApiBizMatchBO apiBizMatchBO) {
        //  时间限制
        String phoneMd5 = apiWakeBO.getPhoneMd5();
        if (DateUtils.timeCompareTo(9) >= 0 && DateUtils.timeCompareTo(23) <= 0) {
            if (!DataExchangeRedisKey.WAKE_PHONE_MD5.setIfAbsentForSeconds(phoneMd5, "1", 600L)) {
                return ;
            }
        } else {
            if (!DataExchangeRedisKey.WAKE_PHONE_MD5.setIfAbsentForSeconds(phoneMd5, "1", 10L)) {
                return ;
            }
        }

        Thread.startVirtualThread(() -> {
            //  唤醒业务
            if (apiWakeBO.getHasLocalExist()) {
                ApiWakeUserBO apiWakeUserBO = getLocalWakeUser(apiWakeBO);
                allocateWake(apiWakeBO, apiWakeUserBO);
            }
            if (apiWakeBO.getHasHistoryExist()) {
                ApiWakeUserBO apiWakeUserBO = getHistoryWakeUser(apiWakeBO);
                allocateWake(apiWakeBO, apiWakeUserBO);
            }
        });
    }

    /**
     *  本地库
     *
     *  @param apiWakeBO        唤醒业务实体类
     */
    private ApiWakeUserBO getLocalWakeUser(ApiWakeBO apiWakeBO) {
        String phoneMd5 = apiWakeBO.getPhoneMd5();
        //  获取用户信息及表单信息
        ChannelUserRegisterPO userRegisterPO = channelUserService.get(ChannelUserQO.createPhoneMd5(phoneMd5));

        //  校验用户名
        String userName = userRegisterPO.getUserName();
        if (!this.validUserName(userName)) {
            return null;
        }

        List<ChannelUserFormFieldPO> listUserForm = channelFormService.listUserFormField(userRegisterPO.getId());
        return ApiWakeUserBO.create(userRegisterPO, listUserForm);
    }

    /**
     *  历史库
     *
     *  @param apiWakeBO  唤醒业务实体类
     */
    private ApiWakeUserBO getHistoryWakeUser(ApiWakeBO apiWakeBO) {
        String phoneMd5 = apiWakeBO.getPhoneMd5();
        //  获取用户信息及表单信息
        ChannelUserRegisterPO userRegisterPO = channelHistoryUserService.get(ChannelUserQO.createPhoneMd5(phoneMd5));

        //  校验用户名
        String userName = userRegisterPO.getUserName();
        if (!this.validUserName(userName)) {
            return null;
        }

        List<ChannelUserFormFieldPO> listUserForm = channelHistoryFormService.listUserFormField(userRegisterPO.getId());

        //  检测是否新库存在，如果不存在则插入到新库
        ChannelUserRegisterPO newUserRegisterPO = channelUserService.get(ChannelUserQO.createPhoneMd5(phoneMd5));
        if (ValidParam.isNull(newUserRegisterPO)) {
            ApiKeyPO apiKeyPO = apiWakeBO.getApiKeyPO();
            channelUserService.insert(userRegisterPO);

            //  拷贝原有表单
            List<ChannelUserFormPO> listChannelUserFormPO = CopyUtils.copyList(listUserForm, ChannelUserFormPO.class);
            IteratorUtils.array(listChannelUserFormPO, t -> {
                t.setChannelId(apiKeyPO.getLoanChannelId());
                t.setUserId(userRegisterPO.getId());
                t.setCreateTime(DateUtils.currentTime());
            });
            channelFormService.batchInsertUserForm(listChannelUserFormPO);
        }
        return ApiWakeUserBO.create(userRegisterPO, listUserForm);
    }

    /**
     *  唤醒业务处理
     *
     *  @param apiWakeBO        唤醒业务实体
     *  @param apiWakeUserBO    唤醒用户信息实体
     */
    private void allocateWake(ApiWakeBO apiWakeBO, ApiWakeUserBO apiWakeUserBO) {
        if (ValidParam.isNull(apiWakeUserBO)) {
            return ;
        }

        //  来源请求id
        String reqId = apiWakeBO.getReqId();

        //  用户数据
        ChannelUserRegisterPO userRegisterPO = apiWakeUserBO.getUserRegisterPO();
        List<ChannelUserFormFieldPO> listUserForm = apiWakeUserBO.getListUserForm();

        //  **********撞库**********
        //  获取唤醒渠道信息-超时时长15s
        ApiKeyCache apiKeyCache = apiKeyCacheService.get(CommonConstant.WAKE_API_CLIENT_ID);
        ApiKeyPO wakeApiKeyPO = CopyUtils.copy(apiKeyCache, ApiKeyPO.class);

        //  唤醒匹配搜索
        ApiWakePlanMatch apiWakePlanMatch = ApiWakePlanMatch.ofMatch(reqId, wakeApiKeyPO, userRegisterPO, listUserForm);
        PlanQualificationResult planQualificationResult = planDataExchangeFacade.searchDistributePlan(apiWakePlanMatch);

        //  校验失败
        PlanQualificationError planQualificationError = planQualificationResult.getValidateFail();
        if (ValidParam.isNotNull(planQualificationError)) {
            return ;
        }

        //  撞库响应
        PlanDistributeResult planDistributeResult = planDataExchangeFacade.channelDataExchange(planQualificationResult);
        if (!planDistributeResult.getDistributeStatus()) {
            return ;
        }

        //  **********进件**********
        try {
            ApiUserRequest apiUserRequest = planQualificationResult.getApiUserRequest();
            planApplyService.wakeApply(apiUserRequest, userRegisterPO, planDistributeResult);
        } catch (Exception e) {
            //  如果是正常API异常则不记录
            if (e instanceof ApiMsgException) {
                return ;
            }
            String stackTrace = ExceptionUtils.getStackTrace(e);
            ProductApplyFlowPO failFlow = CopyUtils.copy(planDistributeResult.getCurrentDistributeFlow(), ProductApplyFlowPO.class);
            failFlow.setExceptionMsg(e.getMessage());
            failFlow.setStackMsg(stackTrace);
            failFlow.setStatus(ProductApplyFlowStatusEnum.APPLY_EXCEPTION.getType());
            productApplyFlowService.insert(failFlow, true);
        }
    }

    /**
     *  创建过滤姓名
     *
     *  @return List
     */
    private static List<String> createFilterUserName() {
        String[] numbers = {"一", "二", "三", "四", "五", "六", "七", "八", "九"};
        String[] units = {"十", "百"};
        List<String> newList = CollUtils.newArrayList();

        for (int i = 0; i <= 9; i++) {
            String unit = units[0];
            for (int j = 0; j < 9; j++) {
                if (i == 0) {
                    newList.add(numbers[j]);
                    if (j == 8) {
                        newList.add(unit);
                    }
                }
                if (i == 1) {
                    newList.add(unit + numbers[j]);
                }
                if (i > 1) {
                    newList.add(numbers[i - 1] + unit + numbers[j]);
                }
            }
        }
        newList.add("一百");
        CollUtils.reverse(newList);
        return newList;
    }

    /**
     *  校验用户名
     *
     *  @param  userName    用户姓名
     *  @return boolean
     */
    private boolean validUserName(String userName) {
        // 不包含特定文字
        if (StringUtils.contains(userName, "客资", "张三", "李四", "默认", "保密", "测试", "姓名", "钱包")) {
            return false;
        }
        // 不能是“保先生”、“保女士”、“未知”
        if(Eq.strOr(userName, "保先生", "保女士", "未知")) {
            return false;
        }
        // 新疆名字(包含"·")不做校验
        if (StringUtils.contains(userName, "·")) {
            return true;
        }
        // 有后缀(先生或女士)不做校验
        if (userName.endsWith("先生") || userName.endsWith("女士")) {
            return true;
        }
        // 长度大于2 或 长度小于4
        int length = userName.length();
        for (String numberSuffix : NUMBER_SUFFIX) {
            if(userName.endsWith(numberSuffix)) {
                //如果是数字后缀，减去数字后缀的长度
                length -= numberSuffix.length();
                break;
            }
        }
        if (length < 2 || length > 4) {
            return false;
        }
        // 是全中文
        return RegexUtils.isChinese(userName);
    }
}
